// TODO: 2025/5/23
//ArrayList的基本操作

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();

        //add方法
        arrayList.add(0,23);
        arrayList.add(1,5);
        arrayList.add(2,2);
        System.out.println(arrayList);
        /*
        add这个源码：
        public void add(int index, E element) {
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();//如果满了就去扩容
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);//原数组，原数组开始拷贝下标，目标数组，目标数组开始的下标，总共拷贝的长度
                         //其实本质都是向后移动为一位，然后直接把目标位置进行修改
        elementData[index] = element;
        size = s + 1;
    }
         */


        System.out.println("===========");


        //boolean addAll(Collection<? extends E> c) ,将一组数据进行全部插入到顺序表的末位处
        ArrayList<Integer> test = new ArrayList<>();
        test.add(1);
        test.add(2);
        test.add(3);//ArrayList<Integer>表示是Collection类型，并且Integer是通配符
        arrayList.addAll(test);//而变量arraylist的Integer是泛型的上界E，而c表示的是test
        System.out.println(arrayList);



        //E remove(int index)传的是下标
        //boolean remove(Object o)传的是数组的对象元素
        System.out.println("==============");
        arrayList.remove(0);
        System.out.println(arrayList);
        arrayList.remove(new Integer(1));//传的是数组的对象的元素，所以直接删除
        System.out.println(arrayList);

        /*
        这个方法从Java9开始就已经过时了，已经很少用了，但是还是可以用，不是不能用了
        @Deprecated(since="9", forRemoval = true)
        public Integer(int value) {
            this.value = value;
        }
         */





        //indexOf和lastIndexOf方法
        System.out.println("==================");
        /*
        public int indexOf(Object o) {
            return indexOfRange(o, 0, size);
        }

        int indexOfRange(Object o, int start, int end) {
            Object[] es = elementData;
            if (o == null) {
                for (int i = start; i < end; i++) {
                    if (es[i] == null) {
                        return i;
                    }
                }
            } else {
                for (int i = start; i < end; i++) {
                    if (o.equals(es[i])) {
                        return i;
                    }
                }
            }
            return -1;
        }
         */
        System.out.println(arrayList.indexOf(new Integer(2)));
        System.out.println(arrayList.indexOf(2));
        //因为传进对象的方法已经过时了，但是我们可以直接传进对象的值，不用特意的再去new一个对象

        System.out.println("=====================");
        System.out.println(arrayList.lastIndexOf(new Integer(2)));
        System.out.println(arrayList.lastIndexOf(2));
        //结论：
        //lastIndexOf从后到前遍历，从而第一次返回了目标对象返回下标
        //IndexOf从前到后遍历，第一次返回目标对象的下标


        System.out.println("======================");

        //List<E> subList(int fromIndex, int toIndex) 截取部分list对象
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);//现在的结果是：1，2，3，4，5
        List<Integer> list1 = list.subList(1,3);//现在的截取是2，3
        //因为ArrayList的类型是Integer,所以是Integer
        System.out.println(list1);
        /*
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList<>(this, fromIndex, toIndex);
        }
        返回的类型是List接口，所以要用list来接收
         */
        System.out.println("==================");
        //但是我们发现了对其进行修改会发生意料之外的情况：
        list1.set(0,99);
        System.out.println(list);//预期结果：1，2，3，4，5
        System.out.println(list1);//预期结果：99，3
        /*
        实际情况：
        [1, 99, 3, 4, 5]
        [99, 3]
        但是我们发现了原来的list发生了改变，并且要改的对应的下标也发生了相同的改变值
         */

        /*
        list : 1 2 3 4 5

        list1: 2 3
        list1的截取是没有在堆上去开辟一个空间去产生一个新的对象，
        而是直接引用截取的ArrayList类型的test的部分元素的地址，
        也就是指向了这些元素的地址，所以是共用相同的对象，所以修改其中哪一个，都会令另一个发生改变
         */

    }
}
/*
ArrayList的问题及思考：
1. ArrayList底层使用连续的空间，任意位置插入或删除元素时，需要将该位置后序元素整体往前或者往后搬移，故时间复杂度为O(N)
2. 增容需要申请新空间，拷贝数据，释放旧空间。会有不小的消耗。
3. 增容一般是呈2倍的增长，势必会有一定的空间浪费。例如当前容量为100，满了以后增容到200，我们再继
续插入了5个数据，后面没有数据插入了，那么就浪费了95个数据空间。

所以我们下节来了解和学习链表
 */